import './SetTable.scss'

import { v4 } from 'uuid'
import { useRequest } from 'alova'
import { useState, useRef, useEffect } from 'react'
import { Select, Button, Tooltip, Tag, Result, Tree, Dropdown, Popconfirm, Popover, Space, Input } from 'antd'
import { ProTable } from '@ant-design/pro-components'
import {
    SaveOutlined,
    OrderedListOutlined,
    UnorderedListOutlined,
    ClearOutlined,
    FundOutlined,
    StockOutlined,
    SlidersOutlined,
    CloseOutlined,
    BuildOutlined,
    DatabaseOutlined,
    DeleteOutlined,
    DownOutlined,
    PlusOutlined
} from '@ant-design/icons'
import { useEventEmitter, useMount, useDrag, useDrop, useReactive, useLatest, } from 'ahooks'

import { Http } from '../../Api'
import { ICONMapping } from '../../Utils/IconMapping'
import { ModelBox } from '../../Model'
import { FormTemplate } from '../../Utils/FormTemp'
import { CustomTableColumns } from './SetTableConfig'
const MenuOptionsMapping = [
    { label: '组织机构拓展', value: 'engineeringOrganizations' },
]

const SettingMapping = [
    { uuid: 1, label: '基础数据', icon: <FundOutlined /> },
    { uuid: 2, label: '字段设置', icon: <StockOutlined /> },
    { uuid: 3, label: '操作设置', icon: <SlidersOutlined /> },
    { uuid: 4, label: '额外菜单', icon: <UnorderedListOutlined /> },
    { uuid: 5, label: '二级页面', icon: <UnorderedListOutlined /> },
    { uuid: 6, label: '三级页面', icon: <UnorderedListOutlined /> },
]

// 基础设置
const SetBaseTemp = ({ OverallEvent, TableInit }) => {
    const ModalEvent = useEventEmitter()

    ModalEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'Added':
                Object.keys(data).forEach(key => TableInit[key] = data[key])
                ModalEvent.emit({ type: 'offLoading' })
                break;
            default:
                break;
        }
    })

    OverallEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'getTable':
                console.log('获取现有table配置', data)
                break;
            default: break;
        }
    })

    return (
        <div className='SetBox SetBaseTemp'>
            <FormTemplate columns={CustomTableColumns} ModalEvent={ModalEvent} init={TableInit} />
        </div>
    )
}
// 字段设置
const SetFieldTemp = ({ OverallEvent, FieldInit }) => {
    const { all, sel } = FieldInit
    OverallEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'getField':
                console.log('field', data)
                setFieldList(data)
                break;
            default: break;
        }
    })

    const TagTemp = ({ title }) => {
        const TagRef = useRef()
        useDrag(title, TagRef)
        if (sel.includes(title)) return <Tag bordered={false} color="processing">{title}</Tag>
        else return <Tag bordered={false} ref={TagRef}>{title}</Tag>
    }

    return (
        <div className='SetBox SetFieldTemp'>
            {all.map(key =>
                <TagTemp key={key} title={key} />
            )}
        </div>
    )
}
// 操作设置
const SetOptionsTemp = ({ LaborInit }) => {
    const { all, item, con, fun } = LaborInit
    const onAddLabor = () => {
        console.log('添加操作')
    }
    const [AllBtnTree, setAllBtnTree] = useState(all)
    const [ItemBtnTree, setItemBtnTree] = useState(item)
    const [OptionsCall, setOptionsCall] = useState()


    const ModalEvent = useEventEmitter()
    ModalEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'modifyStyle':
                const newStyle = { [data.key]: data.style }
                LaborInit.con = { ...con, ...newStyle }
                ModalEvent.emit({ type: 'offLoading' })
                break
            case 'funcConfig':
                const newFunc = { [data.key]: data.func }
                LaborInit.fun = { ...fun, ...newFunc }
                ModalEvent.emit({ type: 'offLoading' })
                break
            default:
                break
        }

    })

    const TreeTemplate = ({ type }) => {
        const DataMap = {
            all: { data: AllBtnTree, set: setAllBtnTree },
            item: { data: ItemBtnTree, set: setItemBtnTree }
        }
        const [open, setOpen] = useState(false)
        const [Status, setStatus] = useState(false)
        const [NewMenu, setNewMenu] = useState('')
        const onDrop = (info, type) => {
            const dropKey = info.node.key;
            const dragKey = info.dragNode.key;
            const dropPos = info.node.pos.split('-');
            const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
            const loop = (data, key, callback) => {
                for (let i = 0; i < data.length; i++) {
                    if (data[i].key === key) return callback(data[i], i, data);
                    if (data[i].children) loop(data[i].children, key, callback);
                }
            };
            const data = [...DataMap[type].data];
            let dragObj;
            loop(data, dragKey, (item, index, arr) => {
                arr.splice(index, 1);
                dragObj = item;
            });
            if (!info.dropToGap) {
                loop(data, dropKey, (item) => {
                    item.children = item.children || [];
                    item.children.unshift(dragObj);
                });
            } else {
                let ar = [];
                let i;
                loop(data, dropKey, (_item, index, arr) => {
                    ar = arr;
                    i = index;
                });
                if (dropPosition === -1) ar.splice(i, 0, dragObj);
                else ar.splice(i + 1, 0, dragObj);
            }
            LaborInit[type] = data
            DataMap[type].set(data)
        }
        const onAdd = () => {
            if (!!!NewMenu) {
                setStatus('error')
                return
            }
            setStatus('')
            const key = v4()
            const newBtn = [...LaborInit[type], { key }]
            LaborInit[type] = newBtn
            LaborInit.con = {
                ...LaborInit.con,
                [key]: {
                    title: NewMenu,
                    icon: 'fangzi',
                    isTitle: true,
                    isIcon: false,
                    iconPosition: 'start',
                    type: 'default',
                    shape: 'default',
                    danger: false,
                    disabled: false,
                    ghost: false,
                    autoInsertSpace: true,
                }
            }
            LaborInit.fun = { ...LaborInit.fun, [key]: {} }
            DataMap[type].set(newBtn)
        }
        const onModifyStyle = (key) => {
            setOptionsCall({
                type: 'SetLadorStyle',
                title: '修改按钮样式',
                data: { key, init: con[key] }
            })
        }
        const onModifyFunc = (key) => {
            setOptionsCall({
                type: 'SetLadorFunc',
                title: con[key].title + ' 按钮功能',
                data: { key, init: fun[key] }
            })
        }
        const onDelBtm = (key) => {
            console.log('删除操作按钮', key)
        }

        return (
            <>
                <Tree
                    className='BtnTree'
                    treeData={type === 'all' ? AllBtnTree : ItemBtnTree}
                    draggable={{ icon: false }}
                    blockNode
                    selectable={false}
                    defaultExpandAll
                    onDrop={(e) => onDrop(e, 'all')}
                    titleRender={({ key }) => {
                        return (
                            <div className='BtnTreeBOM'>
                                <div className='Title'>{con[key].title}</div>
                                <div className='Options'>
                                    <Tooltip title="按钮样式">
                                        <BuildOutlined onClick={() => onModifyStyle(key)} />
                                    </Tooltip>
                                    <Tooltip title="按钮功能">
                                        <DatabaseOutlined onClick={() => onModifyFunc(key)} />
                                    </Tooltip>
                                    <Tooltip title="删除按钮">
                                        <Popconfirm
                                            title="删除提醒!"
                                            description="是否删除当前操作按钮?"
                                            onConfirm={() => onDelBtm(key)}
                                            okText="删除"
                                            cancelText="取消"
                                        >
                                            <DeleteOutlined style={{ color: '#ff7875' }} />
                                        </Popconfirm>
                                    </Tooltip>
                                </div>
                            </div>
                        )
                    }}
                />
                <Popover
                    open={open}
                    trigger="click"
                    onOpenChange={setOpen}
                    content={
                        <Space.Compact style={{ width: 320 }}>
                            <Input status={Status} placeholder='请输入新菜单名称' value={NewMenu} onChange={e => setNewMenu(e.target.value)} />
                            <Button type="primary" onClick={onAdd}>添加</Button>
                        </Space.Compact>
                    }
                >
                    <Button type='primary' icon={<PlusOutlined />}>  添加全局操作 </Button>
                </Popover>
            </>

        )
    }

    return (
        <div className='SetBox SetOptionsTemp'>
            <div className='LoborBox'>
                {all.length === 0 ?
                    <Result
                        status="warning"
                        title="暂无全局操作"
                        extra={<Button type="primary" key="console" onClick={onAddLabor}>添加操作</Button>}
                    /> :
                    <div className='LaborList'>
                        <div className='Title'>全局操作列表</div>
                        <TreeTemplate type={'all'} />
                    </div>
                }
            </div>
            {/* <div className='LoborBox'>
                {item.length === 0 ?
                    <Result
                        status="warning"
                        title="暂无行内操作"
                        extra={<Button type="primary" key="console" onClick={onAddLabor}>添加操作</Button>}
                    /> :
                    <div className='LaborList'>
                        <div className='Title'>行内操作列表</div>
                        <div>
                            操作列表
                        </div>
                    </div>
                }
            </div> */}
            <ModelBox OptionsCall={OptionsCall} ModalEvent={ModalEvent} />
        </div>
    )
}
// 额外菜单
const SetOtherMenuTemp = () => {
    return (
        <div className='SetBox'>额外菜单</div>
    )
}


// 表单部分
const ProTableTemp = ({ OverallEvent, TableInit, FieldInit, LaborInit }) => {
    const { getApi, params } = TableInit
    const RightBox = useRef()
    const actionRef = useRef()
    const [Columns, setColumns] = useState([{ dataIndex: 'uuid', valueType: 'Hidden', hideInTable: true, hideInSearch: true }])
    const ColumnsLast = useLatest(Columns)
    const [OptionsCall, setOptionsCall] = useState()
    const { send: getData } = useRequest(({ url, params }) => Http({ url, params }), { immediate: false })
    const Params = useReactive({ pageIndex: 1, pageSize: 10 })

    const getTableData = async (data) => {
        if (getApi) {
            return getData({ url: getApi, params: { ...data, ...Params } }).then(res => ({ data: res.list, total: res.total, success: true }))
        }
    }

    const ThClick = (e) => {
        setOptionsCall({
            type: 'TableFieldConfig',
            title: e + ' 字段设置',
            width: 1000,
            data: { field: e, init: ColumnsLast.current.find(v => v.dataIndex === e) },
        })
    }

    const onColumnsChange = (e) => {
        const sortedKeys = Object.keys(e)
            .sort((a, b) => {
                const orderA = e[a].order !== undefined ? e[a].order : Infinity;
                const orderB = e[b].order !== undefined ? e[b].order : Infinity;
                return orderA - orderB;
            });
        const indexMap = {}
        Columns.forEach((item, index) => { indexMap[item.dataIndex] = index })
        const reorderedArray = sortedKeys.map(dataIndex => Columns[indexMap[dataIndex]])
        setColumns(reorderedArray)
    }
    useDrop(RightBox, {
        onDom: (e) => {
            FieldInit.sel = [...FieldInit.sel, e]
            setColumns(arr => ([
                ...arr,
                {
                    title: e,
                    dataIndex: e,
                    width: 160,
                    rules: false,
                    hideInTable: false,
                    hideInSearch: false,
                    hideInAdded: false,
                    hideInModify: false,
                    ellipsis: false,
                    copyable: false,
                    tooltip: '',
                    valueType: 'Input',
                    onHeaderCell: () => ({ onClick: () => ThClick(e) })
                }
            ]))
        }
    })
    useEffect(() => {
        const obj = Object.fromEntries(new URLSearchParams(params))
        Object.keys(obj).forEach(key => Params[key] = obj[key])
    }, [params])

    const ModalEvent = useEventEmitter()
    const modifyField = (array, newObj) => array.map(item => item.dataIndex === newObj.dataIndex ? newObj : item)

    ModalEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'modifyField':
                const newData = { ...data, onHeaderCell: () => ({ onClick: () => ThClick(data.dataIndex) }) }
                const arr = modifyField(Columns, newData)
                setColumns(arr)
                ModalEvent.emit({ type: 'TableFieldConfigOff' })
                break;
            case 'deleteField':
                const delData = Columns.filter(v => v.dataIndex !== data)
                const delFiled = FieldInit.sel.filter(v => v !== data)
                FieldInit.sel = delFiled
                setColumns(delData)
                break
            default: break;
        }
    })

    OverallEvent.useSubscription(val => {
        const { type, data } = val
        switch (type) {
            case 'onSave':
                console.log('[保存数据 - 获取Table设置]', Columns)
                break;
            default:
                break;
        }
    })

    return (
        <div className='Right' ref={RightBox}>
            <div className='Menu'></div>
            <div className='Table'>
                <ProTable
                    rowKey="uuid"
                    actionRef={actionRef}
                    columns={Columns}
                    search={TableInit.isSearch}
                    request={getTableData}
                    params={Params}
                    pagination={{
                        pageSize: Params.pageSize,
                        showSizeChanger: true,
                        onChange: (i, s) => {
                            Params.pageIndex = i
                            Params.pageSize = Number(s)
                        },
                    }}
                    headerTitle={TableInit.isTitle ? '表格标题' : ''}
                    columnsState={{ onChange: onColumnsChange }}
                    scroll={{ x: 800, y: 600 }}
                    options={{
                        fullScreen: true,
                        density: false,
                        setting: { checkable: false, checkedReset: false }
                    }}
                    toolBarRender={() => {
                        const { all, con, fun } = LaborInit
                        const ButtonData = all.map(({ key, children }) => {
                            const { title, isTitle, isIcon, icon, ...style } = con[key]
                            const onBtnClick = () => {
                                const { funcType } = fun[key]
                                if (funcType === 'request') {
                                    const { request_api, request_main, request_params, request_mapping, request_additional } = fun[key]
                                    if (request_main) {
                                        setOptionsCall({
                                            type: 'FormAdded',
                                            title: title,
                                            data: { record: fun[key], columns: Columns }
                                        })
                                    }
                                }
                            }


                            if (children) {
                                const items = children.map(({ key }) => ({ key, label: con[key].title }))
                                return (
                                    <Dropdown menu={{ items }}>
                                        <Button  {...style} icon={isIcon && icon && ICONMapping[icon]}> {isTitle && title} </Button>
                                    </Dropdown>
                                )
                            } else {
                                return (
                                    <Button
                                        {...style}
                                        icon={isIcon && icon && ICONMapping[icon]}
                                        onClick={onBtnClick}
                                    >
                                        {isTitle && title}
                                    </Button>
                                )
                            }
                        })
                        return ButtonData
                    }}
                />
            </div>
            <ModelBox OptionsCall={OptionsCall} ModalEvent={ModalEvent} />
        </div>
    )
}

const SetTable = () => {
    const [Active, setActive] = useState()
    const [MenuState, setMenuState] = useState(false)
    const [OptAct, setOptAct] = useState()

    const { send: getTable } = useRequest(params => Http({ url: 'getTable', params }), { immediate: false })
    const { send: getField } = useRequest(params => Http({ url: 'getField', params }), { immediate: false })

    const TableInit = useReactive({})
    const FieldInit = useReactive({ all: [], sel: [] })
    const LaborInit = useReactive({ all: [], item: [] })


    const { send: getJSON } = useRequest(params => Http({ url: 'getField', params }), { immediate: false })


    useMount(() => {

    })



    const onConfirm = () => {
        if (Active) {
            setMenuState(true)
            getTable().then(table => {
                getField().then(field => {
                    Object.keys(table.data).forEach(key => TableInit[key] = table.data[key])
                    const { columns, labor, laborStyle, laborFunc } = table.data
                    FieldInit.all = field.data
                    if (columns.length === 0) {
                        TableInit.columns = ['uuid']
                        FieldInit.sel = ['uuid']
                    } else {
                        FieldInit.sel = columns
                    }
                    LaborInit.all = labor.all
                    LaborInit.item = labor.item
                    LaborInit.con = laborStyle
                    LaborInit.fun = laborFunc
                })
            })
        }
    }
    const onClear = () => {
        setMenuState(false)
        setOptAct()
    }
    const onSave = () => {
        OverallEvent.emit({ type: 'onSave' })
    }
    const onSetClick = (e) => {
        setOptAct(e)
    }

    const OverallEvent = useEventEmitter()
    // OverallEvent.useSubscription(val => {
    //     console.log(val)
    // })




    return (
        <div className='SetTable'>
            <div className='Top'>
                <div className='MenuSelect'>
                    <Select
                        variant="borderless"
                        placeholder='请选择菜单'
                        value={Active}
                        options={MenuOptionsMapping}
                        onChange={setActive}
                        disabled={MenuState}
                    />
                    <Button type='primary' onClick={onConfirm} icon={<OrderedListOutlined />} loading={MenuState}>选定</Button>
                    <Button type='primary' danger onClick={onClear} icon={<ClearOutlined />} loading={!MenuState}>取消</Button>
                </div>
                <Button type='primary' onClick={onSave} icon={<SaveOutlined />} loading={!MenuState}>保存</Button>
            </div>
            <div className='Btm'>
                <div className='Left'>
                    {SettingMapping.map(({ uuid, label, icon }) =>
                        <Tooltip key={uuid} placement='left' title={label}>
                            <Button
                                type='text'
                                icon={icon}
                                onClick={() => onSetClick(uuid)}
                                className={`${OptAct === uuid ? 'active' : ''} animate__animated ${MenuState ? 'animate__backInLeft' : 'animate__backOutLeft'}`}
                            />
                        </Tooltip>
                    )}
                </div>
                <ProTableTemp
                    OverallEvent={OverallEvent}
                    TableInit={TableInit}
                    FieldInit={FieldInit}
                    LaborInit={LaborInit}
                />
            </div>
            <div className='Model' style={{ left: OptAct ? 48 : -400 }} >
                <div className='Title'>
                    <div>{SettingMapping.find(v => v.uuid === OptAct)?.label}</div>
                    <CloseOutlined onClick={() => setOptAct()} />
                </div>
                {(() => {
                    switch (OptAct) {
                        case 1: return <SetBaseTemp OverallEvent={OverallEvent} TableInit={TableInit} />
                        case 2: return <SetFieldTemp OverallEvent={OverallEvent} FieldInit={FieldInit} />
                        case 3: return <SetOptionsTemp OverallEvent={OverallEvent} LaborInit={LaborInit} />
                        case 4: return <SetOtherMenuTemp OverallEvent={OverallEvent} />
                        default: break;
                    }
                })()}
            </div>
        </div>
    )
}

export default SetTable;